package com.yc.anno;

import com.yc.vote.entity.TpUser;
import lombok.Data;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo1 {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        String a = "";
        op(a);
        TpUser user = new TpUser();
        op(user);
        System.out.println("-------------------------");
        op2(A.class);
        System.out.println("-------------------------");
        op2(B.class);
        System.out.println("-------------------------");
        op3();
    }

    public static void op(Object obj){
//        obj instanceof String ==> true
        Class<?> aClass = obj.getClass();
        System.out.println("aClass.getName() = " + aClass.getName());
        System.out.println("aClass.getSimpleName() = " + aClass.getSimpleName());
        try {
            // new Xxxx(); 调用无参数构造函数
            Object obj1 = aClass.newInstance();
            System.out.println("obj.getClass()==obj1.getClass() " +
                    (obj.getClass() == obj.getClass()));
        } catch (InstantiationException e) {
            // 构造函数执行失败
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // 错误访问 => 构造函数的作用域不允许当前方法创建对象
            e.printStackTrace();
        }
    }

    public static void op2(Class<?> cls){
        System.out.println("=========== getFields =============");
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        System.out.println("=========== getDeclaredFields =============");
        fields = cls.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }

    public static void op3() throws InstantiationException, IllegalAccessException {
        A a = A.class.newInstance();
        try {
            Field field = A.class.getDeclaredField("a");
            System.out.println("field = " + field);
            // 设置强制访问非公有的属性(方法,构造...)
            field.setAccessible(true);
            // 相当于 a.a = 10
            field.set(a, 10);
            // 公有属性
            Field gender = A.class.getField("gender");
            gender.set(a,'男');
            System.out.println(a);

            Method hello = A.class.getDeclaredMethod("hello");
            a.name = " world";
            hello.invoke(a);

            hello = A.class.getMethod("hello", String.class);
            hello.invoke(a,"张三");
        } catch (NoSuchFieldException e) {
            // 没有该属性异常
            e.printStackTrace();
        } catch (NoSuchMethodException e){
            // 没有该方法
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // 执行方法内部异常
            e.printStackTrace();
        }

    }


}

@Data
class A {
    private int a;
    protected int b;
    String name;
    public char gender;
    void hello(){
        System.out.println("hello" + name);
    }
    public void hello(String name){
        System.out.println("hello " + name);
    }
}

class B extends A {
    private int c;
    protected int d;
    String type;
    public char status;

    @Override
    void hello() {
        super.hello();
    }
}
